﻿Imports System.Text
Imports System.Timers
Imports TwitterAPI
Imports System.Windows
Imports VsSpeakerCompanion
Imports System.ComponentModel.Composition
Imports System.Windows.Threading
Imports System.Windows.Input
Imports VsSpeakerCompanion.UI

Namespace SpeedWidget
	''' <summary>
	''' Shows what the audience thinks about the pace of the talk
	''' Will try to get the speaker attention if the audience thinks he/she is going too fast or too slow
	''' </summary>
	Friend Class Widget
		Implements IWidget
		' we will be using this service to animate the widget
		Private widgetAnimationService As IWidgetAnimationService
		' our UI
        Private WithEvents view As SpeedView
		' Couple of lists to keep track of received feedback
		Private fastVoters As List(Of String)
		Private slowVoters As List(Of String)

		Public Sub New(ByVal twitterService As TwitterService, ByVal widgetAnimationService As IWidgetAnimationService)
            Me.view = New SpeedView

			' list to clicks on our widget (this means the speaker  the received feedback)
            Me.widgetAnimationService = widgetAnimationService

            fastVoters = New List(Of String)
            slowVoters = New List(Of String)

			' register the two feedback messages this widget understands
			twitterService.RegisterCommand("too fast", AddressOf ProcessTooFastMessages)
			twitterService.RegisterCommand("too slow", AddressOf ProcessTooSlowMessages)

            view.Dispatcher.Invoke(New Action(Sub() UpdateViewSpeed(0.5)))
		End Sub

		''' <summary>
		''' Handles the mouse click event on our widget
		''' </summary>
		''' <param name="source"></param>
		''' <param name="e"></param>
        Private Sub view_MouseDown() Handles view.MouseDown
            ' Clicking on the widget means the speaker acknowledged the received feedback and:
            ' a) the animation should stop and b) the visual indication of too fast or too slow should be reset
            Reset()
        End Sub

		''' <summary>
		''' Keep the count of "too fast" received messages
		''' </summary>
		''' <param name="feedItems"></param>
		Private Sub ProcessTooFastMessages(ByVal feedItems As IEnumerable(Of FeedItem))
			' each user has only a single vote, but he/she can change it at anytime
			' make sure if the user voting has voted before we always remove the previous vote
			feedItems.ToList().ForEach(Sub(item)
				If slowVoters.Contains(item.User) Then
					slowVoters.Remove(item.User)
				End If
			End Sub)
            feedItems.ToList().ForEach(Sub(item)
                                           If Not fastVoters.Contains(item.User) Then
                                               fastVoters.Add(item.User)
                                           End If
                                       End Sub)

			' update our UI with the new vote count
			UpdateSpeed()
		End Sub

		''' <summary>
		''' Keep the count of "too slow" received messages
		''' </summary>
		''' <param name="feedItems"></param>
		Private Sub ProcessTooSlowMessages(ByVal feedItems As IEnumerable(Of FeedItem))
			' each user has only a single vote, but he/she can change it at anytime
			' make sure if the user voting has voted before we always remove the previous vote
			feedItems.ToList().ForEach(Sub(item)
				If fastVoters.Contains(item.User) Then
					fastVoters.Remove(item.User)
				End If
			End Sub)
            feedItems.ToList().ForEach(Sub(item)
                                           If Not slowVoters.Contains(item.User) Then
                                               slowVoters.Add(item.User)
                                           End If
                                       End Sub)

			' update our UI with the new vote count
			UpdateSpeed()
		End Sub

		Private Sub UpdateSpeed()
            Dim totalVotes = fastVoters.Count + slowVoters.Count
			If totalVotes > 0 Then
				widgetAnimationService.Start(Me)
                Dim tooFastPerc = Convert.ToDouble(fastVoters.Count) / Convert.ToDouble(totalVotes)
                Dim speed = tooFastPerc

                view.Dispatcher.Invoke(New Action(Of Double)(Sub(speedArgument) UpdateViewSpeed(speedArgument)), speed)
			Else
                view.Dispatcher.Invoke(New Action(Sub() UpdateViewSpeed(0.5)))
			End If
        End Sub

        Private Sub UpdateViewSpeed(ByVal speed As Double)
            view.Speed = speed
        End Sub

        Public ReadOnly Property VisualElement As UIElement Implements IWidget.VisualElement
            Get
                Return view
            End Get
        End Property

		''' <summary>
		''' Resets our data and start considering new feedback from zero
		''' </summary>
        Public Sub Reset() Implements IWidget.Reset
            fastVoters = New List(Of String)
            slowVoters = New List(Of String)
            view.Dispatcher.Invoke(New Action(Sub() UpdateViewSpeed(0.5)))
            widgetAnimationService.Stop(Me)
        End Sub
	End Class
End Namespace